﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using NicoView.Model.Service;
using NicoView.Model.Service.Comments;
using NicoView.Model.Service.Lives;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using NicoView.ViewModel.Message;
using NicoView.Model.Service.Property;
using NicoView.Model.Service.Events;

namespace NicoView.ViewModel
{
    public sealed class NicoViewCommentEditorViewModel:NicoViewViewModelBase
    {
        public NicoViewCommentEditorViewModel()
        {
            commentWriteExecuteCommand = null;

            currentCommentColor = null;
            currentPosition = null;
            currentSize = null;
            CommentColors = new ObservableCollection<NicoViewCommentColorCommandViewModel>();
            CommentPositions = new ObservableCollection<NicoViewCommentPositionCommandViewModel>();
            CommentSizings = new ObservableCollection<NicoViewCommentSizeCommandViewModel>();
        }



        public INicoCommentClient CommentClient
        {
            get
            {
                if (this.InternalApplication.Instance.CurrentService == null) { return null; }
                return this.InternalApplication.Instance.CurrentService.CommentClient;
            }
        }

        public INicoServiceInfo ServiceInfo
        {
            get
            {
                if (this.InternalApplication.Instance.CurrentService == null) { return null; }
                return this.InternalApplication.Instance.CurrentService.ServiceInfo;
            }
        }



        public void Loded()
        {


            this.InternalApplication.Instance.LiveConnected += args =>
            {
                Set(args.LiveService.MainCommentClient, args.LiveService.LiveServiceInfo);


            };
        }

        



        private ICommand commentWriteExecuteCommand;
        public ICommand CommentWriteExecuteCommand
        {
            get
            {
                if (commentWriteExecuteCommand == null) commentWriteExecuteCommand = new RelayCommand<string>(async(val) =>
                {
                    
                    if (this.CommentClient != null && this.CommentClient.Connected)
                    {
                        this.MessengerInstance.Send(new NotificationMessage("コメント送信中です..."));

                        var comment = new NicoSendComment();
                        comment.Body = val;
                        comment.IsAnonymous = this.InternalApplication.Property.AnonymousSend;
                        comment.IsOwner = this.InternalApplication.Property.OwnerSend;
                        comment.Color = CurrentCommentColor.ColorCommand;
                        comment.Position = CurrentPosition.PositionCommand;
                        comment.Size = CurrentSize.CommentSizeCommand;

                        var result = await this.CommentClient.SendAsync(comment);

                        
                        if (!result.Succeed && result.Value == NicoCommentSendResut.SameAsBeforeComment)
                        {
                            this.MessengerInstance.Send(new NicoViewAlertMessage("前回と同じコメントを送信することはできません"));
                        }
                        else
                        {
                            this.MessengerInstance.Send(new NicoViewCommentEditResetMessage());
                            this.MessengerInstance.Send(new NotificationMessage(""));
                        }
                        
                    }

                });

                return commentWriteExecuteCommand;
            }
        }

        public void Set(NicoLiveCommentClient client, NicoLiveServiceInfo serviceInfo)
        {

            this.CommentClient.SentResult += onSentResult;

            this.RaisePropertyChangedAll();

            CurrentCommentColor = _setMailCommands(CurrentCommentColor, client.Colors, CommentColors, (c) =>
            {
                return new NicoViewCommentColorCommandViewModel(c);
            });


            CurrentPosition = _setMailCommands(CurrentPosition, client.Positions, CommentPositions, (c) =>
            {
                return new NicoViewCommentPositionCommandViewModel(c);
            });


            CurrentSize = _setMailCommands(CurrentSize, client.Sizings, CommentSizings, (c) =>
            {
                return new NicoViewCommentSizeCommandViewModel(c);
            });
  

            this.MessengerInstance.Send(new NicoViewCommentEditorConnectionMessage(client, serviceInfo));
        }


        private void onSentResult(NicoCommentSentResultEventArgs args)
        {

            this.MessengerInstance.Send(new NicoViewSentCommentResultMessage(args.Result));
        }



        public ObservableCollection<NicoViewCommentColorCommandViewModel> CommentColors
        {
            get;
            private set;
        }



        public ObservableCollection<NicoViewCommentPositionCommandViewModel> CommentPositions
        {
            get;
            private set;
            
        }


        public ObservableCollection<NicoViewCommentSizeCommandViewModel> CommentSizings
        {
            get;
            private set;
        }

        private static T _setMailCommands<T, F>(T current, ICollection<F> commandsFrom, ICollection<T> commandsTo, Func<F, T> set)
        {
            commandsTo.Clear();
            foreach (var colorCommand in commandsFrom)
            {
                commandsTo.Add(set(colorCommand));
            }

            return _setCurrentMailCommand(current, commandsTo);
        }

        private static T _setCurrentMailCommand<T>(T current, ICollection<T> commands)
        {
            if (current != null)
            {
                foreach (var command in commands)
                {
                    if (command.GetType() == current.GetType())
                    {
                        current = command;
                        return current;
                    }
                }

            }

            current = commands.First();
            return current;
        }

        private NicoViewCommentColorCommandViewModel currentCommentColor;

        public NicoViewCommentColorCommandViewModel CurrentCommentColor
        {
            get
            {
                return currentCommentColor;
            }
            set
            {
                this.Set(() => this.CurrentCommentColor, ref this.currentCommentColor, value);
            }

        }

        private NicoViewCommentPositionCommandViewModel currentPosition;

        public NicoViewCommentPositionCommandViewModel CurrentPosition
        {
            get
            {
                return currentPosition;
            }
            set
            {
                this.Set(() => this.CurrentPosition, ref this.currentPosition, value);


            }
        }

        private NicoViewCommentSizeCommandViewModel currentSize;

        public NicoViewCommentSizeCommandViewModel CurrentSize
        {
            get
            {
                return currentSize;
            }
            set
            {
                this.Set(() => this.CurrentSize, ref this.currentSize, value);
            }
        }


        
        public bool Connected
        {
            get
            {
                return this.CommentClient != null;
            }


        }


        public bool IsOwner
        {
            get
            {
                return this.ServiceInfo != null && this.ServiceInfo.IsOwner;
            }


        }


        

        public string CurrentText
        {
            get
            {
                return "コマンド";
            }

            set
            {
                return;
            }
        }
    }
}
